﻿using SipClient.SipLib;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Media;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static SipClient.SipLib.Phone;

namespace SipClient
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            //创建录音文件存放目录
            string recordDirectory = _ROOT_PATH + _RECORD_FILE_DIRECTORY;
            if(!Directory.Exists(recordDirectory))
            {
                Directory.CreateDirectory(recordDirectory);
            }
            
            splayer = new SoundPlayer();
        }

        private string _ROOT_PATH = System.Windows.Forms.Application.StartupPath;       //根路径
        private const string _RECORD_FILE_DIRECTORY = "\\record\\";                     //录音文件存放目录
        private const string _RESOURCE_FILE_DIRECTORY = "\\resource\\";                 //资源文件存放目录
        private const string _RECORD_FILE_SUFFIX = ".wav";                              //录音文件后缀名
        private const string _RING_AUDIO_FILE = "ring.wav";                             //振铃资源文件名
        private const string _CALL_AUDIO_FILE = "call.wav";                             //呼叫资源文件名
        private Call outCall;                                                          //主呼会话任务
        private Call inCall;                                                            //被呼会话任务
        private Phone phone;                                                            //软电话实例
        private SoundPlayer splayer;                                                    //音频播放器
        private bool isInit;

        /// <summary>
        /// 向服务器注册手柄，绑定事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void login_Click(object sender, EventArgs e)
        {
            if(!isInit)
            {
                printLog("操作：注册中...");
                string user = this.user.Text;
                string pwd = this.pwd.Text;
                string serverIp = this.serverIp.Text;
                Account account = new Account(user, pwd, serverIp);
                phone = new Phone(account);

                //注册事件
                phone.PhoneConnectedEvent += ConnectedEvent;            //连接事件
                phone.PhoneDisconnectedEvent += DisConnectedEvent;      //断开事件
                phone.ErrorEvent += ErrorEvent;                         //错误事件

                phone.CallActiveEvent += CallActiveEvent;               //呼出任务建立事件
                phone.CallCompletedEvent += CallCompletedEvent;         //挂断事件

                phone.IncomingCallEvent += IncomingCallEvent;           //呼入事件

                phone.Connect();
                isInit = true;
            }

        }

        /// <summary>
        /// 向服务器请求注销手柄
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void logout_Click(object sender, EventArgs e)
        {
            if (phone == null || ConnectState.Connected != phone.CurrentConnectState || isInit != true) return;

            phone.Disconnect();
            isInit = false;
        }

        //功能
        /// <summary>
        /// 挂断
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void hungUp_Click(object sender, EventArgs e)
        {

            if (phone == null || phone.CurrentConnectState != ConnectState.Connected) return;

            LineState state = phone.CurrentLineState;

            //phone.TerminateCall(mainCall);
            phone.TerminateAllCall();
            outCall = null;
            inCall = null;
            printLog("操作：挂断...");

            splayer.Stop();
        }

        /// <summary>
        /// 呼叫通话
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void call_Click(object sender, EventArgs e)
        {
            if (phone == null || phone.CurrentConnectState != ConnectState.Connected || outCall != null) return;

            phone.MakeCall(toNumber.Text);
            printLog("操作：呼叫中...");
        }

        /// <summary>
        /// 录音呼叫通话
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void recordCall_Click(object sender, EventArgs e)
        {
            if (phone == null || phone.CurrentConnectState != ConnectState.Connected || outCall != null) return;

            phone.MakeCallAndRecord(toNumber.Text, CreateFileName());
            printLog("操作：录音呼叫中...");
        }

        /// <summary>
        /// 接听
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void answer_Click(object sender, EventArgs e)
        {
            if (inCall == null || phone == null || phone.CurrentConnectState != ConnectState.Connected) return;
            //Call call = mainCall;
            phone.ReceiveCall(inCall);
            printLog("操作：接听...");
            splayer.Stop();
        }

        /// <summary>
        /// 录音接听
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void recordAnswer_Click(object sender, EventArgs e)
        {
            if (inCall == null || phone == null || phone.CurrentConnectState != ConnectState.Connected) return;

            phone.ReceiveCallAndRecord(inCall, CreateFileName());
            printLog("操作：录音接听...");
            splayer.Stop();
        }

        //end

        //事件
        /// <summary>
        /// 连接注册成功事件
        /// </summary>
        private void ConnectedEvent()
        {
            printLog("事件：已连接到服务器");
            isInit = true;
        }

        /// <summary>
        /// 断开连接事件
        /// </summary>
        private void DisConnectedEvent()
        {
            printLog("事件：与服务器连接已断开");
            isInit = false;
        }

        /// <summary>
        /// 错误事件
        /// </summary>
        /// <param name="call"></param>
        /// <param name="error"></param>
        private void ErrorEvent(Call call, Error error)
        {
            switch(error)
            {
                case Error.RegisterFailed:
                    printLog("错误：注册失败");
                    isInit = false;
                    break;
                case Error.CallError:
                    printLog("错误：呼叫错误");
                    break;
                case Error.LineIsBusyError:
                    printLog("错误：占线中");
                    break;
                case Error.OrderError:
                    printLog("错误：指令错误");
                    break;
                default:
                    printLog("错误：未知错误");
                    break;
            }
        }

        private void CallActiveEvent(Call call)
        {
            printLog("事件：会话已建立...");
            outCall = call;
        }

        /// <summary>
        /// 通话结束事件
        /// </summary>
        /// <param name="call"></param>
        private void CallCompletedEvent(Call call)
        {
            printLog("事件：通话结束");
            outCall = null;
            inCall = null;

            splayer.Stop();
        }

        /// <summary>
        /// 来电事件
        /// </summary>
        /// <param name="call"></param>
        private void IncomingCallEvent(Call call)
        {
            printLog("事件：呼入中，来自：" + call.GetFrom());
            inCall = call;
            splayer.SoundLocation = _ROOT_PATH + _RESOURCE_FILE_DIRECTORY + _RING_AUDIO_FILE;
            splayer.Load();
            splayer.PlayLooping();
        }

        //end

        /// <summary>
        /// 通话日志
        /// </summary>
        /// <param name="value"></param>
        public delegate void PrintLog(string value);
        //委托使用文本框
        void printLog(string value)
        {
            if (this.logText.InvokeRequired)
            {
                PrintLog objSetTextBoxValue = new PrintLog(printLog);

                IAsyncResult result = this.logText.BeginInvoke(objSetTextBoxValue, new object[] { value });
                try
                {
                    objSetTextBoxValue.EndInvoke(result);
                }
                catch
                {
                }
            }
            else
            {
                logText.Text += value + Environment.NewLine;
                logText.Select(logText.Text.Length, 0);
                logText.ScrollToCaret();
            }
        }


        /// <summary>
        /// 创建录音文件名
        /// </summary>
        /// <returns></returns>
        private string CreateFileName()
        {
            string directory = _ROOT_PATH + _RECORD_FILE_DIRECTORY + "\\";
            string fileName = Guid.NewGuid().ToString("N").ToUpper() + _RECORD_FILE_SUFFIX;
            return directory + fileName;
        }

        /// <summary>
        /// 关闭钩子，关闭时注销手柄再退出，否则子线程会导致进程不会关闭
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void hook_close(object sender, FormClosingEventArgs e)
        {
            if(outCall != null)
            {
                outCall = null;
            }

            if(inCall != null)
            {
                inCall = null;
            }

            if (phone != null)
            {
                phone.Disconnect();

                while (true)
                {
                    if(phone.CurrentConnectState != ConnectState.Connected)
                    {
                        System.Environment.Exit(0);
                    }
                    Thread.Sleep(500);
                }
            }

            System.Environment.Exit(0);
        }

    }
}
